package main

import (
	"image/color"
	"fmt"
	"math"
	"sync"
)

type Point struct{ X, Y float64 }
func (p Point) Distance(q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}
func (p *Point) ScaleBy(factor float64) {
	p.X *= factor
	p.Y *= factor
}


//type ColoredPoint struct {
//	Point
//	Color color.RGBA
//}

type ColoredPoint struct {
	*Point
	Color color.RGBA
}

func main() {
	red := color.RGBA{255, 0, 0, 255}
	blue := color.RGBA{0, 0, 255, 255}
	p := ColoredPoint{&Point{1, 1}, red}
	q := ColoredPoint{&Point{5, 4}, blue}
	fmt.Println(p.Distance(*q.Point)) // "5"
	q.Point = p.Point                 // p and q now share the same Point
	p.ScaleBy(2)
	fmt.Println(*p.Point, *q.Point) // "{2 2} {2 2}"

	p1 := Point{1, 2}
	q1 := Point{4, 6}

	distanceFromP := p1.Distance        // method value
	fmt.Println(distanceFromP(q1))      // "5"
	var origin Point                   // {0, 0}
	fmt.Println(distanceFromP(origin)) // "2.23606797749979", sqrt(5)

	scaleP := p1.ScaleBy // method value
	scaleP(2)           // p becomes (2, 4)
	scaleP(3)           //      then (6, 12)
	scaleP(10)          //      then (60, 120)


	p2 := Point{1, 2}
	q2 := Point{4, 6}

	distance := Point.Distance   // method expression
	fmt.Println(distance(p2, q2))  // "5"
	fmt.Printf("%T\n", distance) // "func(Point, Point) float64"

	scale := (*Point).ScaleBy
	scale(&p2, 2)
	fmt.Println(p2)            // "{2 4}"
	fmt.Printf("%T\n", scale) // "func(*Point, float64)"

}

var cache = struct {
	sync.Mutex
	mapping map[string]string
}{
	mapping: make(map[string]string),
}

func Lookup(key string) string {
	cache.Lock()
	v := cache.mapping[key]
	cache.Unlock()
	return v
}
